package com.by.hellospringboot.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.bean.copier.CopyOptions;
import com.by.hellospringboot.controller.request.UserRequestBean;
import com.by.hellospringboot.domain.User;
import com.by.hellospringboot.domain.User_;
import com.by.hellospringboot.domain.repository.UserRepository;
import com.by.hellospringboot.service.UserService;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import javax.persistence.criteria.Predicate;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;

@Service
@Transactional(isolation = Isolation.DEFAULT, propagation = Propagation.REQUIRED, rollbackFor = {Exception.class}, noRollbackFor = {IOException.class})
public class UserServiceImpl implements UserService {

    private final UserRepository userRepository;

    public UserServiceImpl(UserRepository userRepository) {
        this.userRepository = userRepository;
    }


    @Override
    public User create(UserRequestBean bean) {
        User user = new User();
        BeanUtil.copyProperties(bean, user);
        return userRepository.save(user);
    }

    @Override
    public User findById(Long id) {
        return userRepository.getOne(id);
    }

    @Override
    public Page<User> list(int page, int size, String username, Integer maxAge, Integer minAge, Integer gender, String phone, String accessCardNumber, String orderParam, String direction) {
        return userRepository.findAll((Specification<User>) (root, criteriaQuery, criteriaBuilder) -> {
            Predicate predicate = criteriaBuilder.conjunction();
            if (!StringUtils.isEmpty(username)) {
                predicate.getExpressions().add(criteriaBuilder.like(root.get(User_.username), "%" + username + "%"));
            }
            if (maxAge != null) {
                predicate.getExpressions().add(criteriaBuilder.lessThanOrEqualTo(root.get(User_.age), maxAge));
            }
            if (minAge != null) {
                predicate.getExpressions().add(criteriaBuilder.greaterThanOrEqualTo(root.get(User_.age), minAge));
            }
            if (gender != null) {
                predicate.getExpressions().add(criteriaBuilder.equal(root.get(User_.gender), gender));
            }
            if (!StringUtils.isEmpty(phone)) {
                predicate.getExpressions().add(criteriaBuilder.equal(root.get(User_.phone), "%" + phone + "%"));
            }
            if (!StringUtils.isEmpty(accessCardNumber)) {
                predicate.getExpressions().add(criteriaBuilder.like(root.get(User_.accessCardNumber), "%" + accessCardNumber + "%"));
            }
            return predicate;
        }, PageRequest.of(page, size,
                Sort.by(direction == null || direction.toUpperCase(Locale.ROOT).equals("ASC") ? Sort.Direction.ASC : Sort.Direction.DESC,
                        StringUtils.isEmpty(orderParam) ? User_.id.getName() : orderParam)));
    }

    @Override
    public User update(Long id, UserRequestBean bean) {
        User user = findById(id);
        BeanUtil.copyProperties(bean, user);
        return userRepository.save(user);
    }

    @Override
    public User patch(Long id, UserRequestBean bean) {
        User user = findById(id);
        BeanUtil.copyProperties(bean, user, CopyOptions.create().ignoreNullValue());
        return userRepository.save(user);
    }

    @Override
    public void delete(Long id) {
        userRepository.deleteById(id);
    }

    @Override
    public void test() {
        List<UserRequestBean> list = new ArrayList<>();
        for (int i = 0; i < 10; i++) {
            UserRequestBean bean = new UserRequestBean();
            if (i != 8) {
                bean.setUsername(String.format("user%d", i + 1));
            }
            bean.setAge(i + 30);
            list.add(bean);
        }
        for (int i = 0; i < 5; i++) {
            create(list.get(i));
        }
//        testUserService.create();
//        test1();
//        for (int i = 5; i < 10; i++) {
//            create(list.get(i));
//        }
    }

    @Override
    public void test1() {
        for (int i = 0; i < 10; i++) {
            User user = new User();
            if (i != 2) {
                user.setUsername(String.format("test%d", i + 1));
            }
            userRepository.save(user);
        }

    }


}
